var criteria = { Name: "Corporate Governance", Level2: [
    { Name: "Overall Corporate Governance Score", Level3: [
        { Name: "Overall Governance Score", Level4: [{ Name: "Overall Governance Score-Score" }] }
    ]},
    { Name: "Corporate Governance Issues", Level3: [
        { Name: "Board/Management Quality & Integrity", Level4: [
            { Name: "Board/Management Quality & Integrity-Score", IsScreenable: true },
            { Name: "Board/Management Quality & Integrity-Weight", IsScreenable: false },
            { Name: "Board/Management Quality & Integrity-Weighted Score", IsScreenable: false }
        ]},
        { Name: "Board Structure", Level4: [
            { Name: "Board Structure-Score", IsScreenable: true },
            { Name: "Board Structure-Weight", IsScreenable: false },
            { Name: "Board Structure-Weighted Score", IsScreenable: false }
        ]},
        { Name: "Ownership & Shareholder Rights", Level4: [
            { Name: "Ownership & Shareholder Rights-Score", IsScreenable: true },
            { Name: "Ownership & Shareholder Rights-Weight", IsScreenable: false },
            { Name: "Ownership & Shareholder Rights-Weighted Score", IsScreenable: false }
        ]},
        { Name: "Remuneration", Level4: [
            { Name: "Remuneration-Score", IsScreenable: true },
            { Name: "Remuneration-Weight", IsScreenable: false },
            { Name: "Remuneration-Weighted Score", IsScreenable: false }
        ]},
        { Name: "Audit & Financial Reporting", Level4: [
            { Name: "Audit & Financial Reporting-Score", IsScreenable: true },
            { Name: "Audit & Financial Reporting-Weight", IsScreenable: false },
            { Name: "Audit & Financial Reporting-Weighted Score", IsScreenable: false }
        ]},
        { Name: "Stakeholder Governance", Level4: [
            { Name: "Stakeholder Governance-Score", IsScreenable: true },
            { Name: "Stakeholder Governance-Weight", IsScreenable: false },
            { Name: "Stakeholder Governance-Weighted Score", IsScreenable: false }
        ]}
    ]},
    { Name: "Corporate Governance Rank", Level3: [
        { Name: "CG - Rank - Overall", Level4: [{ Name: "CG - Rank - Overall" }] },
        { Name: "CG - Rank - Board/Management Quality & Integrity", Level4: [{ Name: "CG - Rank - Board/Management Quality & Integrity" }] },
        { Name: "CG - Rank - Board Structure", Level4: [{ Name: "CG - Rank - Board Structure" }] },
        { Name: "CG - Rank - Ownership & Shareholder Rights", Level4: [{ Name: "CG - Rank - Ownership & Shareholder Rights" }] },
        { Name: "CG - Rank - Remuneration", Level4: [{ Name: "CG - Rank - Remuneration" }] },
        { Name: "CG - Rank - Audit & Financial Reporting", Level4: [{ Name: "CG - Rank - Audit & Financial Reporting" }] },
        { Name: "CG - Rank - Stakeholder Governance", Level4: [{ Name: "CG - Rank - Stakeholder Governance" }] }
    ]},
    { Name: "Corporate Governance Percentile", Level3: [
        { Name: "CG - Percentile - Overall", Level4: [{ Name: "CG - Percentile - Overall" }] },
        { Name: "CG - Percentile - Board/Management Quality & Integrity", Level4: [{ Name: "CG - Percentile - Board/Management Quality & Integrity" }] },
        { Name: "CG - Percentile - Board Structure", Level4: [{ Name: "CG - Percentile - Board Structure" }] },
        { Name: "CG - Percentile - Ownership & Shareholder Rights", Level4: [{ Name: "CG - Percentile - Ownership & Shareholder Rights" }] },
        { Name: "CG - Percentile - Remuneration", Level4: [{ Name: "CG - Percentile - Remuneration" }] },
        { Name: "CG - Percentile - Audit & Financial Reporting", Level4: [{ Name: "CG - Percentile - Audit & Financial Reporting" }] },
        { Name: "CG - Percentile - Stakeholder Governance", Level4: [{ Name: "CG - Percentile - Stakeholder Governance" }] }
    ]}
]};

function uuid() {
    function s4() {
        return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
    }
    return s4() + s4() + "-" + s4() + "-" + s4() + "-" + s4() + "-" + s4() + s4() + s4();
}

function HexToBase64(hex) {
    var base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    var base64 = "";
    var group;
    for (var i = 0; i < 30; i += 6) {
        group = parseInt(hex.substr(i, 6), 16);
        base64 += base64Digits[(group >> 18) & 0x3f];
        base64 += base64Digits[(group >> 12) & 0x3f];
        base64 += base64Digits[(group >> 6) & 0x3f];
        base64 += base64Digits[group & 0x3f];
    }
    group = parseInt(hex.substr(30, 2), 16);
    base64 += base64Digits[(group >> 2) & 0x3f];
    base64 += base64Digits[(group << 4) & 0x3f];
    base64 += "==";
    return base64;
}

function NUUID(uuid) {
    var hex = uuid.replace(/[{}-]/g, ""); // remove extra characters
    var a = hex.substr(6, 2) + hex.substr(4, 2) + hex.substr(2, 2) + hex.substr(0, 2);
    var b = hex.substr(10, 2) + hex.substr(8, 2);
    var c = hex.substr(14, 2) + hex.substr(12, 2);
    var d = hex.substr(16, 16);
    hex = a + b + c + d;
    var base64 = HexToBase64(hex);
    return new BinData(3, base64);
}

function processLevel1(criteria) {
    var criteriaLevel1Id = db.CriteriaLevel1.findOne({ Name: criteria.Name })._id;

    db.CriteriaLevel2.update(
        {CriteriaLevel1Id: criteriaLevel1Id, Order: {$lt: 10}},
        {$inc: {Order: 10}},
        {multi: true}
    )

    criteria.Level2.forEach(function (criteria, index) {
        processLevel2(criteriaLevel1Id, criteria, index);
    });
}

function processLevel2(criteriaLevel1Id, criteria, index) {
    if (!db.CriteriaLevel2.findOne({ Name: criteria.Name })) {
        db.CriteriaLevel2.insert({
            _id: NUUID(uuid()),
            CriteriaLevel1Id: criteriaLevel1Id,
            UniverseFeature: 15,
            Name: criteria.Name,
            ShortName: 'GovIndicators',
            Order: index
        });
    }

    var criteriaLevel2Id = db.CriteriaLevel2.findOne({ Name: criteria.Name })._id;
    var length = criteria.Level3.length;

    criteria.Level3.forEach(function (criteria, index) {
        processLevel3(criteriaLevel2Id, criteria, length - index);
    });
}

function processLevel3(criteriaLevel2Id, criteria, index) {
    if (!db.CriteriaLevel3.findOne({ Name: criteria.Name, CriteriaLevel2Id: criteriaLevel2Id })) {
        db.CriteriaLevel3.insert({
            _id: NUUID(uuid()),
            Name: criteria.Name,
            ShortName: criteria.Name,
            Order: index,
            CriteriaLevel2Id: criteriaLevel2Id,
            Category: "None",
        });
    }

    var criteriaLevel3Id = db.CriteriaLevel3.findOne({ Name: criteria.Name, CriteriaLevel2Id: criteriaLevel2Id })._id;

    criteria.Level4.forEach(function (criteria) {
        processLevel4(criteriaLevel2Id, criteriaLevel3Id, criteria, index);
    });
}

function processLevel4(criteriaLevel2Id, criteriaLevel3Id, criteria, index) {
    if (!db.OldTemplateCriteria.findOne({ Name: criteria.Name, CriteriaLevel2Id: criteriaLevel2Id })) {
        db.OldTemplateCriteria.insert({
            _id: NUUID(uuid()),
            Name: criteria.Name,
            CriteriaEntity: "ScreeningData",
            CriteriaEntityField: criteria.Name.replace('.', ''),
            Score: null,
            TemplateIndicatorNumber: null,
            CriteriaLevel2Id: criteriaLevel2Id,
            CriteriaType: 16,
            FilterId: null,
            CompaniesIdsResult: null,
            Order: index
        });
    }

    if (!db.TemplateCriteria.findOne({ Name: criteria.Name, CriteriaLevel2Id: criteriaLevel2Id })) {
        db.TemplateCriteria.insert({
            _id: NUUID(uuid()),
            Name: criteria.Name,
            CriteriaEntity: "ScreeningData",
            CriteriaEntityField: criteria.Name.replace('.', ''),
            CriteriaType: 16,
            CriteriaLevel2Id: criteriaLevel2Id,
            CriteriaLevel3Id: criteriaLevel3Id,
            IsScreenable: criteria.IsScreenable != undefined ? criteria.IsScreenable : true
        });
    }
}

use ClientPlatform

processLevel1(criteria);
